﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using S3.DataModel;
using S3.Common;

namespace S3.Biz
{
    /// <summary>
    /// Lưu các mặt hàng đã bán hàng ngày. Mỗi bản ghi là 1 mặt hàng.
    /// </summary>
    public class DailyItemEntryManager : CommonManager
    {
        #region constants

        private static string UnPaid = DailyAddditonalItemEntryStatusValue.Text[AdditonalItemEntryStatus.UnPaid];
        private static string Paid = DailyAddditonalItemEntryStatusValue.Text[AdditonalItemEntryStatus.Paid];

        #endregion

        /// <summary>
        /// Get one item entry by ID
        /// </summary>
        /// <param name="itemEntryID"></param>
        /// <returns></returns>
        #region GetOneByID
        public DailyItemEntry GetOneByID(long itemEntryID)
        {
            try
            {
                return _entities.DailyItemEntries.Where(a => a.ItemEntryID == itemEntryID).FirstOrDefault();
            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyItemEntryManager::GetOneByID::", ex, true);
                }
            }

            return null;
        }
        #endregion

        /// <summary>
        /// Tinh tien hang hoa da mua theo hoa don
        /// Tien nay da bao gom thue tren tung mat hang
        /// </summary>
        /// <param name="deskName"></param>
        /// <returns></returns>
        #region GetNotPaidByDesk
        public decimal CalcMoneySoldItemsByInvoice(string invoiceNo)
        {
            try
            {
                var items = GetAllByInvoice(invoiceNo);
                //Kiem tra so luong hang hoa
                if (items != null && items.Count() > 0)
                {
                    //Thuc hien tinh toan
                    return items.Sum(i => i.Amount);
                }

            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyAdditionalItemEntryManager::GetAllByInvoice::", ex, true);
                }
            }

            return 0;
        }
        #endregion

        /// <summary>
        /// Load tat ca hang hoa theo Hoa don
        /// </summary>
        /// <param name="deskName"></param>
        /// <returns></returns>
        #region GetAllByInvoice
        public IQueryable<DailyItemEntry> GetAllByInvoice(string invoiceNo)
        {
            try
            {

                return _entities.DailyItemEntries.Where(a => a.InvoiceNo == invoiceNo);

            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyAdditionalItemEntryManager::GetAllByInvoice::", ex, true);
                }
            }

            return null;
        }
        #endregion

        /// <summary>
        /// Load tat ca hang hoa chua thanh toan theo ban (hoa don)
        /// </summary>
        /// <param name="deskName"></param>
        /// <returns></returns>
        #region GetUnpaidByDesk
        public IQueryable<DailyItemEntry> GetUnpaidByDesk(string invoiceNo)
        {
            try
            {

                return _entities.DailyItemEntries.Where(a => a.Status == UnPaid && a.InvoiceNo == invoiceNo);

            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyItemEntryManager::GetUnpaidByDesk::" + invoiceNo, ex, true);
                }
            }

            return null;
        }
        #endregion

        public void FinishSession(string staffName)
        {
            var listService = GetPaid().Where(a => a.SessionBy == null || a.SessionBy == string.Empty);
            foreach (var item in listService)
            {
                item.SessionBy = staffName;
                item.ModifiedBy = staffName;
                item.ModifiedDate = DateTime.Now;
            }

            _entities.SaveChanges();
        }

        /// <summary>
        /// Load tat ca do goi them cua may hien tai da tra tien nhung chua ban giao
        /// SessionBy = (null || empty)
        /// </summary>
        /// <param name="deskName"></param>
        /// <returns></returns>
        #region GetPaidBySession

        public IQueryable<DailyItemEntry> GetPaid()
        {
            try
            {

                return _entities.DailyItemEntries.Where(a => a.Status.ToLower() == Paid);
            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyAdditionalItemEntryManager::GetPaid::", ex, true);
                }
            }

            return null;
        }

        public List<ExtendService> GetPaidBySession(ref decimal totalServiceMoney)
        {
            var result = new List<ExtendService>();

            try
            {
                var rawList = GetPaid().Where(a => a.SessionBy == null || a.SessionBy == string.Empty);

                var customList = from o in rawList
                                 group o by o.ItemName into g
                                 select new { ServiceName = g.Key, Quantity = g.Sum(a => a.Quantity), Money = g.Sum(o => o.Amount) };

                foreach (var item in customList)
                {
                    totalServiceMoney = totalServiceMoney + item.Money;
                    ExtendService n = new ExtendService()
                    {
                        ItemName = item.ServiceName,
                        Quantity = item.Quantity,
                        TotalServiceMoney = Utils.StringFormatMoney(item.Money)
                    };

                    result.Add(n);
                }

            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyAdditionalItemEntryManager::GetPaidBySession::", ex, true);
                }
            }

            return result;
        }
        #endregion

        /// <summary>
        /// Load tat ca do goi them cua may hien tai va tinh tong tien
        /// </summary>
        /// <param name="deskName"></param>
        /// <returns></returns>
        #region CalTotalServiceMoneyByDesk
        public decimal CalTotalTimingServiceMoneyByInvoice(string invoiceNo)
        {
            //Check parameter
            if (string.IsNullOrEmpty(invoiceNo)) return 0;
            decimal total = 0;
            try
            {
                var entries = GetUnpaidByDesk(invoiceNo);

                total = entries.Sum(m => m.Amount);

            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyAdditionalItemEntryManager::CalTotalServiceMoneyByDesk::", ex, true);
                }
            }

            return total;
        }
        #endregion

        #region Add

        /// <summary>
        /// Save entry to SQL
        /// </summary>
        /// <param name="dailyEntry"></param>
        public int Add(DailyItemEntry dailyEntry)
        {
            try
            {
                DailyItemEntry entry = null;
                //Check exist first
                // If existing then update else add new
                if (IsExist(dailyEntry.TimingServiceName, dailyEntry.ItemName, ref entry))
                {
                    entry.Quantity = entry.Quantity + dailyEntry.Quantity;
                    entry.ModifiedBy = Common.Constants.StaffName;
                    entry.ModifiedDate = DateTime.Now;
                }
                else
                {
                    //Add new
                    if (dailyEntry.ItemEntryID == 0)
                    {
                        dailyEntry.ModifiedBy = Common.Constants.StaffName;
                        dailyEntry.ModifiedDate = DateTime.Now;
                        dailyEntry.Status = DailyAddditonalItemEntryStatusValue.Text[AdditonalItemEntryStatus.UnPaid];

                        _entities.AddToDailyItemEntries(dailyEntry);
                    }
                }

                //Submit change
                return _entities.SaveChanges();
                //ActionLogger.LogAction(ActionType.AddService, Constants.StaffName, DateTime.Now, new string[] { dailyEntry.ItemName, Convert.ToString(dailyEntry.Quantity), dailyEntry.TimingServiceName });

            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyAdditionalItemEntryManager::Add::" + dailyEntry.TimingServiceName, ex, true);
                }
            }

            return 0;

        }
        #endregion

        /// <summary>
        /// Dieu chinh so luong hang hoa trong kho de ban.
        /// Tim cac lo hang co cung BarCode voi so luong > 0 va san sang de ban
        /// </summary>
        /// <param name="itemEntryId"></param>
        /// <param name="barCode"></param>
        /// <param name="qtyToExport"></param>
        /// <param name="remainingQty"></param>
        /// <returns>0: Khong ban | 1: Ban thanh cong | 2: Kho Khong du SL de ban</returns>
        public int SubtractItemQtyInStockForSale(string barCode, decimal qtyToExport, ref decimal remainingQty)
        {
            IQueryable<GoodsStore> listItemSameBarcode = null;
            using (GoodsStoreManager manager = new GoodsStoreManager())
            {
                var listItems = manager.GetAll();
                if (listItems != null)
                {
                    //Loc hang hoa cung Ma Vach co so luong > 0.
                    listItemSameBarcode = listItems.Where(i => i.BarCode == barCode && i.QtyInStock.Value > 0 && i.Status == ItemStatusValue.Text[ItemStatus.Avaiable]).OrderBy(i => i.ImportDate);//Sap xep theo tu thu hang cu truoc moi sau.
                    remainingQty = 0;//So luong hang con lai 
                    decimal qtyAdjusted = 0;//So luong hang da ban
                    foreach (var item in listItemSameBarcode)
                    {
                        remainingQty = qtyToExport - qtyAdjusted;
                        if (remainingQty > 0)
                        {
                            manager.AdjustItemQuantity(item.ItemID, qtyToExport, false, ref qtyAdjusted);
                        }
                    }

                    if (remainingQty == 0)
                    {
                        return 1;
                    }

                    if (remainingQty > 0)
                    {
                        return 2;
                    }
                }

            }

            return 0;
        }

        #region Save
        /// <summary>
        /// Save entry to SQL
        /// </summary>
        /// <param name="dailyEntry"></param>
        public void Save(DailyItemEntry dailyEntry)
        {
            try
            {
                DailyItemEntry entry = null;
                //Check exist first
                // If existing then update else add new
                if (IsExist(dailyEntry.TimingServiceName, dailyEntry.ItemName, ref entry))
                {
                    entry.Quantity = dailyEntry.Quantity;
                    entry.ModifiedBy = Common.Constants.StaffName;
                    entry.ModifiedDate = DateTime.Now;
                }
                else
                {
                    //Add new
                    if (dailyEntry.ItemEntryID == 0)
                    {
                        dailyEntry.ModifiedBy = Common.Constants.StaffName;
                        dailyEntry.ModifiedDate = DateTime.Now;
                        dailyEntry.Status = DailyAddditonalItemEntryStatusValue.Text[AdditonalItemEntryStatus.UnPaid];

                        _entities.AddToDailyItemEntries(dailyEntry);
                    }
                }

                //Submit change
                _entities.SaveChanges();
                //ActionLogger.LogAction(ActionType.AddService, Constants.StaffName, DateTime.Now, new string[] { dailyEntry.ItemName, Convert.ToString(dailyEntry.Quantity), dailyEntry.TimingServiceName });
            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyAdditionalItemEntryManager::Save::" + dailyEntry.TimingServiceName, ex, true);
                }
            }

        }
        #endregion

        /// <summary>
        /// Check existing or not
        /// </summary>
        /// <param name="deskName"></param>
        /// <param name="itemName"></param>
        /// <returns></returns>
        public bool IsExist(string deskName, string itemName, ref DailyItemEntry entry)
        {
            //Check parameter
            if (string.IsNullOrEmpty(deskName) || string.IsNullOrEmpty(itemName)) return false;

            try
            {
                entry = _entities.DailyItemEntries.FirstOrDefault(a => a.Status == UnPaid && a.TimingServiceName == deskName && itemName == a.ItemName);
                return entry == null ? false : true;
            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyAdditionalItemEntryManager::IsExist::" + deskName + "|" + itemName, ex, true);
                }
            }

            return false;
        }

        /// <summary>
        /// Stop playing
        /// </summary>
        /// <param name="deskName"></param>
        #region StopPlaying
        public void StopPlaying(string deskName, long deskStopingID)
        {
            try
            {
                var servicesList = GetUnpaidByDesk(deskName);

                using (GoodsStoreManager unitPriceManager = new GoodsStoreManager())
                {
                    IQueryable<GoodsStore> unitPriceList = unitPriceManager.GetAll();

                    foreach (var item in servicesList)
                    {
                        item.Status = DailyAddditonalItemEntryStatusValue.Text[AdditonalItemEntryStatus.Paid];
                        item.Amount = Convert.ToDecimal(((unitPriceList.Where(a => a.ItemName.ToLower() == item.ItemName.ToLower()).Select(a => a.UnitPrice)).FirstOrDefault() * item.Quantity));
                        item.ModifiedDate = DateTime.Now;
                        item.ModifiedBy = Constants.StaffName;
                        item.DailyTimingEntryID = deskStopingID;
                    }
                }

                _entities.SaveChanges();
            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyAdditionalItemEntryManager::StopPlaying::" + deskName, ex, true);
                }
            }
        }
        #endregion

        /// <summary>
        /// Chuyen tat ca do goi them cua may hien tai sang may dich
        /// </summary>
        /// <param name="deskName"></param>
        #region SwitchDesk
        public void SwitchDesk(string currentDesk, string destinationDesk)
        {
            try
            {
                //Chuyen ban hien tai
                var currentDeskServicesList = GetUnpaidByDesk(currentDesk);
                foreach (var item in currentDeskServicesList)
                {
                    item.TimingServiceName = destinationDesk;
                    item.ModifiedBy = Constants.StaffName;
                    item.ModifiedDate = DateTime.Now;
                }

                //Chuyen tu ban Dich va ban hien tai
                var destinationDeskServicesList = GetUnpaidByDesk(destinationDesk);
                foreach (var item in destinationDeskServicesList)
                {
                    item.TimingServiceName = currentDesk;
                    item.ModifiedBy = Constants.StaffName;
                    item.ModifiedDate = DateTime.Now;
                }

                _entities.SaveChanges();
            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyAdditionalItemEntryManager::SwitchDesk::" + currentDesk + "|" + destinationDesk, ex, true);
                }
            }
        }
        #endregion

        #region ReportGameMoneyResult
        /// <summary>
        /// Bao cao tien game
        /// </summary>
        /// <param name="currentDate"></param>
        /// <param name="reportType"></param>
        /// <param name="totalMoney"></param>
        /// <returns></returns>
        public List<ReportDailyServiceMoney> ReportServiceMoneyResult(DateTime currentDate, ReportType reportType, ref decimal totalMoney)
        {
            List<ReportDailyServiceMoney> result = new List<ReportDailyServiceMoney>();
            try
            {
                //Get finished records                
                var list = _entities.DailyItemEntries.Where(a => a.Status.ToLower() == Paid);

                if (list != null || list.Count() > 0)
                {

                    switch (reportType)
                    {
                        case ReportType.Daily:
                            list = list.Where(a => a.ModifiedDate.Day == currentDate.Day && a.ModifiedDate.Month == currentDate.Month && a.ModifiedDate.Year == currentDate.Year && a.Quantity > 0);
                            break;
                        case ReportType.Monthly:
                            list = list.Where(a => a.ModifiedDate.Month == currentDate.Month && a.ModifiedDate.Year == currentDate.Year && a.Quantity > 0);
                            break;

                    }

                    var customList = from o in list
                                     group o by o.ItemName into g
                                     select new { ServiceName = g.Key, Quantity = g.Sum(a => a.Quantity), ServiceMoney = g.Sum(o => o.Amount) };

                    foreach (var item in customList)
                    {
                        totalMoney = totalMoney + item.ServiceMoney;

                        ReportDailyServiceMoney reportServiceMoney = new ReportDailyServiceMoney()
                        {
                            ServiceName = item.ServiceName,
                            Quantity = item.Quantity,
                            ServiceMoney = Utils.StringFormatMoney(item.ServiceMoney)
                        };

                        result.Add(reportServiceMoney);
                    }
                }
            }
            catch (Exception ex)
            {
                using (var exception = new SSDLoggingHandler())
                {
                    exception.BizException("DailyAdditionalItemEntryManager::ReportServiceMoneyResult::", ex, true);
                }
            }

            return result;
        }
        #endregion
    }
}
